/**
 * 
 */
package oop.data;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import com.google.gson.FieldNamingStrategy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class TestVersionData {

	private static Random random = new Random(System.currentTimeMillis());
	
	private Map<Long, Long[]> questionsOrder;
	private Map<Long, Map<Long, Long[]>> answersOrder;

	public TestVersionData() {
		// default constructor
	}
	
	public TestVersionData(Map<Long, Long[]> questionOrder,
			Map<Long, Map<Long, Long[]>> answerOrder) {
		this.questionsOrder = questionOrder;
		this.answersOrder = answerOrder;
	}

	public static TestVersionData fromTest(Test test) throws SQLException {
		// generate version
		Map<Long, Long[]> questionOrder = new HashMap<Long, Long[]>();
		Map<Long, Map<Long, Long[]>> answerOrder = new HashMap<Long, Map<Long,Long[]>>();
		
		for (Section section : test.getSections()) {
			Long[] questionIds = new Long[section.getQuestions().size()];
			section.getQuestionById().keySet().toArray(questionIds);
			shuffle(questionIds);
			questionOrder.put(section.getId(), questionIds);
			
			Map<Long, Long[]> questionMap = new HashMap<Long, Long[]>();
			for (Question question : section.getQuestions()) {
				Long[] answerIds = new Long[question.getUsedAnswers().size()];
				question.getAnswerById().keySet().toArray(answerIds);
				shuffle(answerIds);
				questionMap.put(question.getId(), answerIds);
			}
			answerOrder.put(section.getId(), questionMap);
		}
		return new TestVersionData(questionOrder, answerOrder);
	}
	
	private static <T> void shuffle(T[] arr) {
		for (int i = 0; i < arr.length; i++) {
			int r = random.nextInt(arr.length);
			T t = arr[i];
			arr[i] = arr[r];
			arr[r] = t;
		}
	}

	private static Gson getGson() {
		return new GsonBuilder().setFieldNamingStrategy(new FieldNamingStrategy() {
			
			@Override
			public String translateName(Field f) {
				if ("questionsOrder".equals(f.getName())) {
					return "q";
				} 
				if ("answersOrder".equals(f.getName())) {
					return "a";
				}
				return f.getName();
			}
		}).create();
	}

	public String toJson() {
		return getGson().toJson(this);
	}
	
	public static TestVersionData fromJson(String json) {
		return getGson().fromJson(json, TestVersionData.class);
	}
	
	public Map<Long, Long[]> getQuestionsOrder() {
		return questionsOrder;
	}
	
	public Map<Long, Map<Long, Long[]>> getAnswersOrder() {
		return answersOrder;
	}

}